<template>
  <div class="person">
    <h1>情况四:监视【ref】或【reactive】定义的【对象类型】数据中的某个属性</h1>
    <h2>姓名:{{ person.name }}</h2>
    <h2>年龄:{{ person.age }}</h2>
    <h2>汽车:{{ person.car.c1 }},{{ person.car.c2 }}</h2>
    <button @click="changeName">修改姓名</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeC1">修改第一台车</button>
    <button @click="changeC2">修改第二台车</button>
    <button @click="changeCar">修改整个车</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import { reactive, watch } from "vue";

  //数据
  let person = reactive({
    name: "张三",
    age: 18,
    car: {
      c1: "奔驰",
      c2: "宝马",
    },
  });

  //方法
  function changeName() {
    person.name += "~";
  }
  function changeAge() {
    person.age += 1;
  }
  function changeC1() {
    person.car.c1 = "AMG";
  }
  function changeC2() {
    person.car.c2 = "M4";
  }
  function changeCar() {
    person.car = { c1: "雅马哈", c2: "川崎" };
  }

  /* 结论监视的要是对象里的属性,那么最好写成函数式
    注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视
  */

  //监视, 情况四:监视响应式对象中的某个属性,且该属性是基本类型的,要写成函数式(箭头函数)
  watch(
    () => person.name,
    (newValue, oldValue) => {
      console.log("person.name变化了", newValue, oldValue);
    }
  );
  //监视, 情况四:监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写person.car，也能写函数,但更推荐写成函数式
  watch(
    () => person.car, //写成函数式就相当于监视car的地址值了,如果就写person.car就只是监视car的值，所以当修改整个车(调用changeCar())的时候就监视不到了，因为地址发生改变了，没写{deep:true}时写成函数式值修改C1或者C2又监视不到了，写了就可以了
    (newValue, oldValue) => {
      console.log("person.car变化了", newValue, oldValue);
    },
    { deep: true }
  );
</script>

<style scoped>
  .person {
    background-color: aqua;
    box-shadow: 0 0 10px;
    border-radius: 10px;
    padding: 20px;
  }

  button {
    margin-left: 5px;
    margin-right: 5px;
  }
</style>
